using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using NETL.Engine.Destination;
using NETL.Engine.Source;
using NETL.Engine.Transformation;
using NETL.Data.Context;
using NETL.Data.Config;
using NETL.Engine.WF;
using System.Workflow.Runtime;

namespace NETL.Engine.Context
{
	public class Pipeline
	{
		private ILog myLogger = LogManager.GetLogger(typeof(Pipeline));
		private string myName;
		private string myDescription;
		private List<IMessageSource> mySources;
		private List<IMessageDestination> myTargets;
		private List<ITransformation> myTransformations;
		private bool myIsActive = false;
		private Dictionary<Guid, WorkflowInstance> myWorkFlows = new Dictionary<Guid, WorkflowInstance>();

		public bool IsActive
		{
			get { return myIsActive; }
			set { myIsActive = value; }
		}

		public string Name
		{
			get { return myName; }
			set { myName = value; }
		}

		public string Description
		{
			get { return myDescription; }
			set { myDescription = value; }
		}

		public List<IMessageSource> Sources
		{
			get { return mySources; }
			set { mySources = value; }
		}

		public List<IMessageDestination> Targets
		{
			get { return myTargets; }
			set { myTargets = value; }
		}

		public List<ITransformation> Transformations
		{
			get { return myTransformations; }
			set { myTransformations = value; }
		}


		public void Start()
		{
			bool testSuccess = true;

			foreach (IMessageSource source in mySources)
			{
				ExecutionResult res = source.Test();

				if (res.Status != ExecutionStatus.Success)
				{
					testSuccess = false;
					myLogger.Error(string.Format("Test() failed for \"{0}\", message \"{0}\".", source.Name, res.Message), res.Exception);
					break;
				}
			}

			if (testSuccess)
			{
				foreach (IMessageSource source in mySources)
				{
					source.Error += new ReceiveError(MessageSource_Error);
					source.Started +=new SourceStarted(MessageSource_Started);
					source.Stopped +=new SourceStopped(MessageSource_Stopped);
					source.Received +=new MessageReceived(MessageSource_Received);
					source.Start();
				}
			}
		}

		public void Stop()
		{
			foreach (IMessageSource source in mySources)
			{
				source.Stop();
			}			
		}


		private void MessageSource_Received(IMessageSource source, NETL.Engine.Data.IMessage message)
		{
			Dictionary<string, object> dict = new Dictionary<string, object>();
			dict.Add("Pipeline", this);
			dict.Add("Transformations", Transformations);
			dict.Add("Destinations", Targets);
			dict.Add("Message", message);


			// Store message to new state
			// do Transformations
			// execute destinations

			WorkflowInstance wfInstance = ExecutionContext.Instance().WorkflowRuntime.CreateWorkflow(typeof(Delivery), dict);
			
			wfInstance.Start();
		}

		private void MessageSource_Stopped(IMessageSource source)
		{
			source.Error -= new ReceiveError(MessageSource_Error);
			source.Started -= new SourceStarted(MessageSource_Started);
			source.Stopped -= new SourceStopped(MessageSource_Stopped);
			source.Received -= new MessageReceived(MessageSource_Received);
		}

		private void MessageSource_Started(IMessageSource source)
		{
			throw new NotImplementedException();
		}

		private void MessageSource_Error(IMessageSource source, ExecutionResult result)
		{
			throw new NotImplementedException();
		}

	}
}
